﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Boardgame;
using BoardgameModelViewed;
using WpfGameControls;


namespace WpfChess
{
    public partial class App : Application
    {
    }


    public class ChessView : IChessView
    {
        private ChessController controller;
        private ChessModelBase modelbase;

        internal ChessView (ChessController wpfController, ChessModelBase modelbase)
        {
            this.controller = wpfController;
            this.modelbase = modelbase;

            this.modelbase.SetView (this);

            this.modelbase.GameCreated += ShowNewGame;
            this.modelbase.StatusUpdate += UpdateStatus;
            this.modelbase.TokenRemove += wpfController.ClearContent;
            this.modelbase.TokenPlace += PlaceToken;
            this.modelbase.MoveProcess += ProcessMove;
            this.modelbase.UndoPreview += PreviewUndo;
            this.modelbase.HiliteChange += wpfController.ChangeHilite;
            this.modelbase.HilitesClear += wpfController.ClearHilites;

            ShowNewGame();
            UpdateStatus();
        }

        #region IChessView implementation

        public void ShowMessage (string message, Player toPlayer)
        {
            WpfMessageBox.Show
            (
                message,
                "Message to " + ChessModelBase.PlayerName (toPlayer)
            );
        }

        public bool ShowQuestion (string message, Player toPlayer)
        {
            MessageBoxResult result = WpfMessageBox.ShowQuestion
            (
                message,
                "Message to " + ChessModelBase.PlayerName (toPlayer)
            );

            return result == MessageBoxResult.OK || result == MessageBoxResult.Yes;
        }

        #endregion

        #region Model event handlers

        private void ShowNewGame ()
        {
            controller.moveList.Items.Clear();

            for (int cellY = 0; cellY < modelbase.Board.SizeY; ++cellY)
                for (int cellX = 0; cellX < modelbase.Board.SizeX; ++cellX)
                {
                    var piece = modelbase.Board[cellX, cellY] as Piece;

                    if (piece == null)
                        controller.ClearContent (cellX, cellY);
                    else
                        PlaceToken (cellX, cellY, piece.Side, piece.Token);
                }
        }


        private void UpdateStatus ()
        {
            controller.promoList.Text = modelbase.CurrentPlayerPromotionName;
            string[] list = modelbase.GetStatusText();

            controller.statusTurn.Text = list[0];
            controller.status1.Text = list[1];
            controller.status2.Text = list[2];

            UpdateEnables();
        }


        private void UpdateEnables ()
        {
            bool isPlaying = modelbase != null && modelbase.IsUnderway;

            controller.gameMenuResign.IsEnabled = isPlaying;
            controller.gameMenuUndo.IsEnabled = isPlaying && modelbase.Plies.Count > 0;
            controller.promoList.IsEnabled = isPlaying;
            controller.drawMenu.IsEnabled = isPlaying;
            controller.drawMenuRequest.IsEnabled = isPlaying;
            controller.drawMenuFiftyMoves.IsEnabled = isPlaying && modelbase.IsFiftyMoveRuleClaimable;
            controller.drawMenuRepetitionNow.IsEnabled = isPlaying && modelbase.IsThreefoldRepRuleClaimable;
            controller.drawMenuRepetitionLater.IsEnabled = isPlaying;
            controller.drawMenuRepetitionLater.IsChecked = modelbase.IsThreefoldRepDrawOnMoveRequested;
        }


        private void PlaceToken (int cellX, int cellY, Player player, Token token)
        {
            if (token == Token.Empty)
                controller.ClearContent (cellX, cellY);
            else
                // Display Unicode chess character.
                controller.SetContent (cellX, cellY, ((char) (0x2653 + (int) player * 6 + (int) token)).ToString());
        }


        private void ProcessMove ()
        {
            int lastItem;
            Ply ply = modelbase.Plies.Top;
            string newText = ply.ToString();

            controller.Selection = null;

            if (ply.Moving.Side == Player.Black)
            {
                lastItem = controller.moveList.Items.Count - 1;
                string text = (string) controller.moveList.Items[lastItem];
                controller.moveList.Items[lastItem] = text + "  " + newText;
            }
            else
            {
                int turnNumber = modelbase.Plies.Count / 2 + 1;
                lastItem = controller.moveList.Items.Count;
                controller.moveList.Items.Add (turnNumber.ToString () + ".  " + newText);
            }

            controller.moveList.Focus();
            controller.moveList.SelectedItem = controller.moveList.Items[lastItem];
        }


        private void PreviewUndo ()
        {
            int lastItem = (modelbase.Plies.Count - 1) / 2;
            if (modelbase.Plies.Count % 2 == 0)
                controller.moveList.Items[lastItem] = (lastItem+1).ToString() + ".  "
                                            + modelbase.Plies[modelbase.Plies.Count-2].ToString();
            else
                controller.moveList.Items.RemoveAt (lastItem);
        }

        #endregion
    }
}
